package cn.zhx.domain.award.service.distribute.impl;


import cn.zhx.domain.award.model.aggregate.GiveOutPrizesAggregate;
import cn.zhx.domain.award.model.entity.DistributeAwardEntity;
import cn.zhx.domain.award.model.entity.UserAwardRecordEntity;
import cn.zhx.domain.award.model.entity.UserCreditAwardEntity;
import cn.zhx.domain.award.model.valobj.AwardStateVO;
import cn.zhx.domain.award.respository.IAwardRepository;
import cn.zhx.domain.award.service.distribute.IDistributeAward;
import cn.zhx.types.common.Constants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.MathContext;

/**
 *  用户随机积分奖品发奖，支持 award_config 透传，满足黑名单积分奖励。
 */
@Component("user_credit_random")
public class UserCreditRandomAward implements IDistributeAward {

    @Resource
    private IAwardRepository repository;

    @Override
    public void giveOutPrizes(DistributeAwardEntity distributeAwardEntity) {
        // 奖品ID
        Integer awardId = distributeAwardEntity.getAwardId();
        // 查询奖品配置 「优先走透传的随机积分奖品配置」
        String awardConfig = distributeAwardEntity.getAwardConfig();
        if (StringUtils.isBlank(awardConfig)) {
            awardConfig = repository.queryAwardConfig(awardId);
        }
        //随机积分: awardConfig = 1,100
        String[] creditRange = awardConfig.split(Constants.SPLIT);
        if (creditRange.length != 2) {
            throw new RuntimeException("award_config 「" + awardConfig + "」配置不是一个范围值，如 1,100");
        }

        // 生成随机积分值
        BigDecimal creditAmount = generateRandom(new BigDecimal(creditRange[0]), new BigDecimal(creditRange[1]));

        // 构建聚合对象
        UserAwardRecordEntity userAwardRecordEntity = GiveOutPrizesAggregate.buildDistributeUserAwardRecordEntity(
                distributeAwardEntity.getUserId(),
                distributeAwardEntity.getOrderId(),
                distributeAwardEntity.getAwardId(),
                AwardStateVO.complete
        );

        UserCreditAwardEntity userCreditAwardEntity = GiveOutPrizesAggregate.buildUserCreditAwardEntity(distributeAwardEntity.getUserId(), creditAmount);

        GiveOutPrizesAggregate giveOutPrizesAggregate = new GiveOutPrizesAggregate();
        giveOutPrizesAggregate.setUserId(distributeAwardEntity.getUserId());
        giveOutPrizesAggregate.setUserAwardRecordEntity(userAwardRecordEntity);
        giveOutPrizesAggregate.setUserCreditAwardEntity(userCreditAwardEntity);

        // 存储发奖对象
        repository.saveGiveOutPrizesAggregate(giveOutPrizesAggregate);
    }

    /**
     * 生成介于最小值和最大值之间的随机BigDecimal数。
     *
     * 此方法解决了Java中生成大数范围随机数的难题，通过利用BigDecimal的精度控制，
     * 可以确保生成的随机数在给定的大数范围内，且精度可控。
     *
     * @param min 最小值，包含在随机数范围内。
     * @param max 最大值，包含在随机数范围内。
     * @return 介于最小值和最大值之间的随机BigDecimal数，精度控制在3位小数。
     */
    private BigDecimal generateRandom(BigDecimal min, BigDecimal max) {
        // 如果最小值等于最大值，则直接返回最小值，因为范围内只有一个数。
        if (min.equals(max)) return min;

        // 生成一个随机的BigDecimal数，其值在0到(max-min)之间。
        // 然后将其加到min上，以确保结果在[min, max]范围内。
        BigDecimal randomBigDecimal = min.add(BigDecimal.valueOf(Math.random()).multiply(max.subtract(min)));

        // 对结果进行四舍五入，保留3位小数。
        // 这样做可以控制随机数的精度，避免因过大或过小的数值导致的精度问题。
        return randomBigDecimal.round(new MathContext(3));
    }


}
